package com.sztx.pay.center.rpc.component;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.mortbay.log.Log;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;

import com.alibaba.dubbo.common.utils.StringUtils;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.sztx.pay.center.common.util.Constance;
import com.sztx.pay.center.common.util.Constance.CallBackOrderState;
import com.sztx.pay.center.common.util.Constance.TradeMessageType;
import com.sztx.pay.center.common.util.Constance.TradeOrderType;
import com.sztx.pay.center.common.util.Constance.UserActType;
import com.sztx.pay.center.common.util.JFUtils;
import com.sztx.pay.center.common.util.StringUtil;
import com.sztx.pay.center.common.util.ValidateUtil;
import com.sztx.pay.center.core.service.AccountService;
import com.sztx.pay.center.core.service.ActService;
import com.sztx.pay.center.core.service.CallBackService;
import com.sztx.pay.center.core.service.MqMessageService;
import com.sztx.pay.center.core.service.OrderMappingService;
import com.sztx.pay.center.core.service.PayCoreService;
import com.sztx.pay.center.core.service.SettleService;
import com.sztx.pay.center.core.service.UserInfoService;
import com.sztx.pay.center.core.service.bean.CallBackInfo;
import com.sztx.pay.center.core.service.bean.ConfirmPoJo;
import com.sztx.pay.center.core.service.bean.PayeeInfo;
import com.sztx.pay.center.dataaccess.dao.mysql.OrderB2cMysqlDAO;
import com.sztx.pay.center.dataaccess.dao.mysql.OrderConfirmDetailMysqlDAO;
import com.sztx.pay.center.dataaccess.dao.redis.LockRedisDAO;
import com.sztx.pay.center.dataaccess.domain.OrderB2cDO;
import com.sztx.pay.center.dataaccess.domain.OrderConfirmDetailDO;
import com.sztx.pay.center.dataaccess.domain.UserActDO;
import com.sztx.pay.center.dataaccess.domain.UserBindCardDO;
import com.sztx.pay.center.dataaccess.domain.UserInfoDO;
import com.sztx.pay.center.rpc.api.domain.ConfirmOrderRequest;
import com.sztx.pay.center.rpc.api.domain.SettleRequest;
import com.sztx.pay.center.rpc.api.domain.TradeBaseRequest;
import com.sztx.pay.center.rpc.api.domain.TradeFlowMessage;
import com.sztx.pay.center.rpc.api.domain.TradeResponse;
import com.sztx.se.common.exception.BusinessException;

public class TradeConfirmOrderService extends TradeService {

	@Autowired
	CallBackService callBackService;
	
	@Autowired
	OrderConfirmDetailMysqlDAO orderConfirmDAO;
	
	@Autowired
	private ActService actService;
	
	@Autowired
	private UserInfoService userInfoService;
	
	@Autowired
	OrderMappingService orderMappingService;
	
	@Autowired
	private LockRedisDAO lockRedisDAO;
	
	@Autowired
	private MqMessageService mqMessageService;
	
	public PayCoreService getPayCoreService() {
		return payCoreService;
	}

	public void setPayCoreService(PayCoreService payCoreService) {
		this.payCoreService = payCoreService;
	}

	public SettleService getSettleService() {
		return settleService;
	}

	public void setSettleService(SettleService settleService) {
		this.settleService = settleService;
	}

	public OrderB2cMysqlDAO getOrderB2cMysqlDAO() {
		return orderB2cMysqlDAO;
	}

	public void setOrderB2cMysqlDAO(OrderB2cMysqlDAO orderB2cMysqlDAO) {
		this.orderB2cMysqlDAO = orderB2cMysqlDAO;
	}

	PayCoreService payCoreService;

	SettleService settleService;

	OrderB2cMysqlDAO orderB2cMysqlDAO;

//	AccountService accountService;
	
	public AccountService getAccountService() {
		return accountService;
	}

	public void setAccountService(AccountService accountService) {
		this.accountService = accountService;
	}

	@Override
	void checkPrivateParam(Map<String, String> params) {

		String tadeOrderId = params.get("tadeOrderId");
		String userProfit = params.get("userProfit");
		String settleJson = params.get("settleJson");
		String orderId = params.get("orderId");
		Long userProfitAmount = 0L;
		if (!StringUtil.isEmpty(userProfit)) {
			userProfitAmount = new Long(userProfit);
		}
		ValidateUtil.isNotBlank(tadeOrderId, "tradeOrderId不能为空!");

		OrderB2cDO b2cDO = orderB2cMysqlDAO.findByOrderIdAndId(tadeOrderId, orderId);
		if (b2cDO == null)
			throw new BusinessException("该交易订单不存在:[" + tadeOrderId + "]!");

		Long orderPayAmount = b2cDO.getPayAmount();
		Long totalAmount = 0L;
		
		if (b2cDO.getOrderStatus() != Constance.B2COrderState.SUCCESS.getCode() && b2cDO.getOrderStatus() != Constance.B2COrderState.SETTLE_FAIL.getCode()&& b2cDO.getOrderStatus() != Constance.B2COrderState.TRADE_OVER.getCode())
			throw new BusinessException("当前订单状态不能确认收货!");

		if (!StringUtils.isBlank(settleJson)) {
			List<SettleRequest> settles = JSONArray.parseArray(settleJson,
					SettleRequest.class);
			if (!CollectionUtils.isEmpty(settles)){
				for (SettleRequest settleRequest : settles) {
					String payeeUserId = settleRequest.getUserId();
					getUserCashActInfo(payeeUserId, b2cDO.getPlatChannelId());
					int amount = settleRequest.getAmount();
					if (amount <= 0) {
						throw new BusinessException("分销结算金额不能小于等于0");
					}
					totalAmount = totalAmount + amount;
				}
			}


		}
		totalAmount = totalAmount + userProfitAmount + b2cDO.getFee();
		if (totalAmount.compareTo(orderPayAmount) == 1)
			throw new BusinessException("用户的分润金额与商户结算金额及手续费总和不能大于订单总额!");

	}

	@Override
	boolean isRepeatOrder(Map<String, String> params) {
		
		String tadeOrderId = params.get("tadeOrderId");
		
		boolean lockOrder = lockRedisDAO.lockOrder(tadeOrderId, "0", "checkConfirmRepeat", 5l);
		
		if (!lockOrder) return true;
		
		return false;
	}

	@Override
	String recordOrder(TradeBaseRequest request) {
		return null;
	}

	@Override
	UserBindCardDO getPayerBindInfo(Map<String, String> params) {
		return null;
	}

	@Override
	UserBindCardDO getPayeeBindInfo(Map<String, String> params) {
		return null;
	}

	@Override
	UserActDO getPayerActInfo(TradeBaseRequest request) {
		return null;
	}

	@Override
	UserActDO getPayeeActInfo(TradeBaseRequest request) {
		return null;
	}

	@Override
	TradeResponse invokePayCore(Map<String, String> params) {
		String tadeOrderId = params.get("tadeOrderId");
		String userProfit = params.get("userProfit");
		Long userProfitAmount = 0L;
		if (!StringUtil.isEmpty(userProfit)) {
			userProfitAmount = new Long(userProfit);
			
		}
		String settleJson = params.get("settleJson");
		String notifyUrl = params.get("notifyUrl");
		String returnUrl = params.get("returnUrl");
		
		
		OrderB2cDO b2cDO = orderB2cMysqlDAO.findById(tadeOrderId);
		
		if (b2cDO.getOrderStatus() == Constance.B2COrderState.TRADE_OVER.getCode()) {
			TradeResponse resp = new TradeResponse();
			resp.setTradeOrderId(tadeOrderId);
			resp.setResultCode("3");
			resp.setResultMsg("确认收货成功");
			return resp;
		}
		ConfirmPoJo confirmResult = comfirmOrder(tadeOrderId, userProfitAmount, settleJson, false,b2cDO.getOrderId());
		int states = confirmResult.getState();
		
		
		if (states != Constance.PayFlowState.PAYING.getCode()) {
			CallBackInfo callBackInfo = new CallBackInfo();
			callBackInfo.setTradeOrderId(tadeOrderId);
			callBackInfo.setOutOrderId(b2cDO.getOrderId());
			callBackInfo.setNotfiyUrl(notifyUrl);
			callBackInfo.setReturnUrl(returnUrl);
			callBackInfo.setTotalFee(0);
			callBackInfo.setPayAmount(b2cDO.getTradeAmount().intValue());
			callBackInfo.setAttach(b2cDO.getAttach());
			callBackInfo.setPayTime(new Date());
			callBackInfo.setTradeCrateTime(b2cDO.getAddTime());
			callBackInfo.setOrderType(TradeOrderType.SETTLE_ORDER);
			
			if (states == Constance.PayFlowState.FAIL.getCode() ) {
				callBackInfo.setOrderState(CallBackOrderState.FAIL);
			} else if (states == Constance.PayFlowState.EXCEPTION.getCode() ){
				callBackInfo.setOrderState(CallBackOrderState.EXCEPTION);
			} else {
				callBackInfo.setOrderState(CallBackOrderState.SUCCESS);
			}
			callBackService.callBack(callBackInfo);
		}
		
		TradeResponse response = new TradeResponse();
		response.setResultCode(String.valueOf(states));
		response.setTradeOrderId(tadeOrderId);
		response.setResultMsg(confirmResult.getMsg());
		return response;
	}
	
	public void asyncComfirmOrder(String tadeOrderId, Long userProfit, String settleJson, boolean isSettleNow,String outOrderId) {
		comfirmOrder(tadeOrderId, userProfit, settleJson, isSettleNow,outOrderId);
	}
	
	public ConfirmPoJo comfirmOrder(String tadeOrderId, Long userProfit, String settleJson, boolean isSettleNow,String outOrderId) {
		List<PayeeInfo> payeeInfos = new ArrayList<PayeeInfo>();
		
		OrderB2cDO b2cDO = orderB2cMysqlDAO.findById(tadeOrderId);
		String businessType = b2cDO.getBusinessType();
		Integer fee = b2cDO.getFee();
		if (userProfit == null) {
			userProfit = 0l;
		}
		if (fee == null) {
			fee = 0;
		}
		if (b2cDO.getOrderStatus().intValue() != Constance.B2COrderState.SUCCESS.getCode() && b2cDO.getOrderStatus().intValue() != Constance.B2COrderState.SETTLE_FAIL.getCode()){
			logger.warn("当前订单状态不能确认收货!"+b2cDO.getOrderStatus());
			ConfirmPoJo resp = new ConfirmPoJo();
			resp.setState(2);
			resp.setMsg("");
			return resp;
		}
		
		Long settleAmount = new Long(0);

		//确认收货记录信息
		List<ConfirmOrderRequest> confirmOrderRequests = new ArrayList<ConfirmOrderRequest>();
		
		
		// String attach = params.get("attach");
		// 商户结算
		if (!StringUtils.isBlank(settleJson)) {
			List<SettleRequest> settles = JSONArray.parseArray(settleJson,
					SettleRequest.class);
			if(!CollectionUtils.isEmpty(settles)) {
				for (SettleRequest settleRequest : settles) {
					if(settleRequest == null){
						continue;
					}
					int amount = settleRequest.getAmount();
					String payeeUser = settleRequest.getUserId();
					
					PayeeInfo payeeInfo = new PayeeInfo();
					payeeInfo.setAmount(amount);
					payeeInfo.setPayeeUser(payeeUser);
					payeeInfo.setTradeOrderType(TradeOrderType.SETTLE_DISTRIBUTOR);
					payeeInfos.add(payeeInfo);
					
					settleAmount = settleAmount + amount;
					
					ConfirmOrderRequest confirmOrderRequest = new ConfirmOrderRequest();
					confirmOrderRequest.setOutOrderId(outOrderId);
					confirmOrderRequest.setTradeOrderId(tadeOrderId);
					confirmOrderRequest.setAmount(amount);
					confirmOrderRequest.setRemark("结算给分销商");
					confirmOrderRequest.setUserId(payeeUser);
					confirmOrderRequests.add(confirmOrderRequest);
				}
			}
		}
		// 用户返利结算
		if (userProfit != null && userProfit != 0) {
			PayeeInfo payeeInfo = new PayeeInfo();
			payeeInfo.setAmount(userProfit);
			payeeInfo.setPayeeUser(Constance.USER_REBATE);
			payeeInfo.setTradeOrderType(TradeOrderType.SETTLE_PROFIT);
			
			payeeInfos.add(payeeInfo);
			settleAmount = settleAmount + userProfit;
			
			ConfirmOrderRequest confirmOrderRequest = new ConfirmOrderRequest();
			confirmOrderRequest.setOutOrderId(outOrderId);
			confirmOrderRequest.setTradeOrderId(tadeOrderId);
			confirmOrderRequest.setAmount(userProfit);
			confirmOrderRequest.setRemark("商家支付返利金");
			confirmOrderRequest.setUserId(Constance.USER_REBATE);
			confirmOrderRequests.add(confirmOrderRequest);
			
		}
		// 扣除结算剩下给商家的钱
		Long payAmount = b2cDO.getPayAmount();
		String payeeUserId = b2cDO.getPayeeUserId();
		Long remainAmount = payAmount - settleAmount - fee;

		if(remainAmount != 0) {
			PayeeInfo info = new PayeeInfo();
			info.setAmount(remainAmount);
			info.setPayeeUser(payeeUserId);
			info.setTradeOrderType(TradeOrderType.SETTLE_ORDER);
			
			payeeInfos.add(info);
			
			
			
			ConfirmOrderRequest confirmOrderRequest = new ConfirmOrderRequest();
			confirmOrderRequest.setOutOrderId(outOrderId);
			confirmOrderRequest.setTradeOrderId(tadeOrderId);
			confirmOrderRequest.setAmount(remainAmount);
			confirmOrderRequest.setRemark("交易结算给商家");
			confirmOrderRequest.setUserId(payeeUserId);
			confirmOrderRequests.add(confirmOrderRequest);
		}
		
		//记录确认收货信息
		recordConfirmDetail(confirmOrderRequests,tadeOrderId,outOrderId);
		
		
		
		// 构建参数并且调用结算接口,结算都是从商户的交易账户转移到商户及其分销商的现金账户
		com.sztx.pay.center.core.service.bean.SettleRequest request = new com.sztx.pay.center.core.service.bean.SettleRequest();
		request.setPayerUser(b2cDO.getPayeeUserId());
		request.setPayeeInfo(payeeInfos);
		request.setOrderId(tadeOrderId);
		request.setAttach("确认收货结算");
		request.setPerPayeeHandingFee(false);
		request.setBusinessType(businessType);
		logger.info("b2cDO.getFee()" + b2cDO.getFee());
		if (b2cDO.getFee() != null) {
			request.setHandingFee(b2cDO.getFee());
		} else {
			request.setHandingFee(0);
		}
		logger.info("request.getHandingFee()" + request.getHandingFee());
		// 更新B2C订单状态
		OrderB2cDO updateOrderB2cDO = new OrderB2cDO();
		updateOrderB2cDO.setTradeOrderId(tadeOrderId);
		updateOrderB2cDO.setOrderStatus(Constance.B2COrderState.SETTLING
				.getCode());
		updateOrderB2cDO.setOrderDesc(Constance.B2COrderState.SETTLING.getDesc());
		orderB2cMysqlDAO.updateInfo(updateOrderB2cDO);
		//结算结果 1未支付,2 支付中,3 成功,4 失败,5 异常
		int settleNowState = 3;
		ConfirmPoJo resp = new ConfirmPoJo();
		resp.setState(settleNowState);
		if (isSettleNow) {
			resp = settleService.settleNow(request, "confirmOrderServiceImpl");
		} else {
			settleService.settleLatter(request, "confirmOrderServiceImpl");
			resp.setMsg("结算中");
			resp.setState(2);
		}
		if (resp.getState() == Constance.PayFlowState.SUCCESS.getCode()) {
			TradeFlowMessage message = new TradeFlowMessage();
			
			message.setTradeType(TradeMessageType.SETTLE.getCode());
			message.setBerbonAcc(b2cDO.getPayeeUserId());
			message.setBusinessType(b2cDO.getBusinessType());
			message.setTradeAmount(b2cDO.getTradeAmount());
			message.setReceiveAmount(remainAmount);
			message.setOtherBerbonAcc(b2cDO.getPayerUserId());
			message.setPayOrderNo(tadeOrderId);
			message.setTradeOrderNo(b2cDO.getOrderId());
			message.setFee(b2cDO.getFee());
			message.setProfit(settleAmount);
			
			sendTradeFlowMessage(message);
		}
		return resp;
	}


	@Override
	void handerPayCoreResult() {

	}

//	@Override
//	public void callPayResult(PayCoreTradeInfo tradeInfo) {
//		
//		logger.info("into confirmOrderCallBack");
//		String referOrderId = tradeInfo.getReferOrderId();
//		int payFlowState = tradeInfo.getPayFlowState().getCode();
//		logger.info("confirmOrderCallBack referOrderId:" + referOrderId);
//		logger.info("confirmOrderCallBack payFlowState:" + payFlowState);
//		
//		OrderB2cDO orderB2cDO = orderB2cMysqlDAO.findById(referOrderId);
//		
//		if (orderB2cDO != null && orderB2cDO.getOrderStatus() == Constance.B2COrderState.SETTLING.getCode()) {
//			//更新订单状态
//			OrderB2cDO updateOrderB2cDO = new OrderB2cDO();
//			if (payFlowState == Constance.PayFlowState.SUCCESS.getCode()) updateOrderB2cDO.setOrderStatus(Constance.B2COrderState.TRADE_OVER.getCode());
//			if (payFlowState == Constance.PayFlowState.FAIL.getCode()) updateOrderB2cDO.setOrderStatus(Constance.B2COrderState.SETTLE_FAIL.getCode());
//			if (payFlowState == Constance.PayFlowState.EXCEPTION.getCode()) updateOrderB2cDO.setOrderStatus(Constance.B2COrderState.SETTLE_EXCEPTION.getCode());
//			updateOrderB2cDO.setTradeOrderId(referOrderId);
//			orderB2cMysqlDAO.updateInfo(updateOrderB2cDO);
//			//通知业务系统
//			CallBackInfo callBackInfo = new CallBackInfo();
//			callBackInfo.setTradeOrderId(referOrderId);
//			callBackInfo.setOutOrderId(orderB2cDO.getOrderId());
//			callBackInfo.setNotfiyUrl(orderB2cDO.getNotifyUrl());
//			callBackInfo.setReturnUrl(orderB2cDO.getReturnUrl());
//			callBackInfo.setTotalFee(0);
//			callBackInfo.setPayAmount(orderB2cDO.getTradeAmount().intValue());
//			callBackInfo.setAttach(orderB2cDO.getAttach());
//			callBackInfo.setPayTime(new Date());
//			callBackInfo.setTradeCrateTime(orderB2cDO.getAddTime());
//			callBackInfo.setOrderType(TradeOrderType.SETTLE_ORDER);
//			
//			if (payFlowState == Constance.PayFlowState.FAIL.getCode() ) {
//				callBackInfo.setOrderState(CallBackOrderState.FAIL);
//			} else if (payFlowState == Constance.PayFlowState.EXCEPTION.getCode() ){
//				callBackInfo.setOrderState(CallBackOrderState.EXCEPTION);
//			} else {
//				callBackInfo.setOrderState(CallBackOrderState.SUCCESS);
//			}
//			
//			callBackService.callBack(callBackInfo);
//		}
//	}
	
	
	
	private void recordConfirmDetail(List<ConfirmOrderRequest> confirmOrderRequests,String tradeOrderId,String outOrderId){
		if(CollectionUtils.isEmpty(confirmOrderRequests)){
			return;
		}
		List<OrderConfirmDetailDO> orderConfirmDetailDOs = orderConfirmDAO.findByTradeOrderId(tradeOrderId);
		if(CollectionUtils.isEmpty(orderConfirmDetailDOs)){
			for (ConfirmOrderRequest confirmOrderRequest : confirmOrderRequests) {
				OrderConfirmDetailDO orderConfirmDetailDO = new OrderConfirmDetailDO();
				orderConfirmDetailDO.setTradeOrderId(confirmOrderRequest.getTradeOrderId());
				orderConfirmDetailDO.setOutOrderId(confirmOrderRequest.getOutOrderId());
				orderConfirmDetailDO.setAmount(confirmOrderRequest.getAmount());
				orderConfirmDetailDO.setUserId(confirmOrderRequest.getUserId());
				orderConfirmDetailDO.setRemark(confirmOrderRequest.getRemark());
				orderConfirmDetailDOs.add(orderConfirmDetailDO);
			}
			Log.info("orderConfirmDetailDOs:"+JSONObject.toJSONString(orderConfirmDetailDOs));
			orderConfirmDAO.batchsave(orderConfirmDetailDOs);
		}else{
			List<ConfirmOrderRequest> confirmDaoOrderRequests = new ArrayList<ConfirmOrderRequest>();
			for (OrderConfirmDetailDO orderConfirmDetailDO : orderConfirmDetailDOs) {
				ConfirmOrderRequest confirmOrderRequest = new ConfirmOrderRequest();
				confirmOrderRequest.setOutOrderId(orderConfirmDetailDO.getOutOrderId());
				confirmOrderRequest.setTradeOrderId(orderConfirmDetailDO.getTradeOrderId());
				confirmOrderRequest.setAmount(orderConfirmDetailDO.getAmount());
				confirmOrderRequest.setRemark(orderConfirmDetailDO.getRemark());
				confirmOrderRequest.setUserId(orderConfirmDetailDO.getUserId());
				confirmDaoOrderRequests.add(confirmOrderRequest);
			}
			if(confirmDaoOrderRequests.size() == confirmOrderRequests.size() && confirmDaoOrderRequests.contains(confirmOrderRequests)){
				Log.info("重复发起确认收货,不作记录");
			}else{
				throw new BusinessException("订单【"+outOrderId+"】确认收货信息与之前提交信息不一致!");
			}
			
		}
	}

	UserActDO getUserCashActInfo(String userId, String channelId) {
		
		UserActDO payerUser = null;
		//查询用户详情
		UserInfoDO userInfoDO = userInfoService.findUserInfo(userId);
		if (userInfoDO == null ) throw new BusinessException(userId + "账户不存在");
		
		//用户角色组合1+4+8+16
		Integer userType = userInfoDO.getUserType();
		
		if (JFUtils.isJFChannel(channelId)) {
			if((UserActType.JF.getuType() & userType) == 0) throw new BusinessException(userId + "账户不是缴费账户!");
			payerUser = actService.findUserAct(userId, UserActType.JF);
		} else {
			payerUser = actService.findUserAct(userId, UserActType.CASH);
		}

		if (payerUser == null) {
			throw new BusinessException(userId + "账户不存在");
		}
		//赋值用户账号类型角色
		payerUser.setUserType(userType);

		return payerUser;
	}
	
	private boolean sendTradeFlowMessage(TradeFlowMessage message) {
		String json = JSONObject.toJSONString(message);
		mqMessageService.sendTradeFlowMsg(json);
		return true;
	}
}
